
/**	
*	
	Doyle Spiral
*/

import ij.ImagePlus;
import ij.plugin.PlugIn;
import ij.process.ColorProcessor;
import ij.process.ImageProcessor;

import java.awt.Color;
import java.awt.Font;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Random; 


import pluginUtils.DoyleCircle;


public class doyle3_ extends ImagePlus implements PlugIn {
	private ImageProcessor primeIP; 
	private int X=2000,Y=2000;
	private Random generator=new Random(); 
	private ArrayList<DoyleCircle> memoire=new ArrayList<DoyleCircle>();
	private ArrayList<DoyleCircle> traites=new ArrayList<DoyleCircle>();
	private ArrayList<DoyleCircle> traces=new ArrayList<DoyleCircle>();
	private int order=0;
	
	private int module=100; 
	
	
	private float redColor[]=new float[module]; 
	private float blueColor[]=new float[module];
	private float greenColor[]=new float[module];
	
	private boolean first=true; 
	
	private void drawCircle(DoyleCircle c){
		//if(intersect(c))return; 
		int intX=(int)(c.getXcenter()*X);
		int intY=(int)(c.getYcenter()*Y);
		int intR=(int)(c.getRadius()*X); // X ??
		primeIP.setColor(new Color(redColor[order%module],greenColor[order%module],blueColor[order%module]));
		if(first){
			first=false;
			primeIP.fillOval(intX-intR,intY-intR,intR*2,intR*2);
			primeIP.moveTo(intX-85,intY+20); 
		//	primeIP.drawString("Origin");
		}
		else{
		primeIP.fillOval(intX-intR,intY-intR,intR*2,intR*2);
		primeIP.moveTo(intX-85,intY+20); 
		//primeIP.drawString(order+"");
		}
		order++;
	}
	
	

	public void run(String arg) {
		primeIP = new ColorProcessor(X,Y);
		DoyleCircle.setBounds(0,0);
		double a=1.03;
		double b=a*a*a*a*a;
		double  n=5.0; 
		double  m=4.0; 
		//double b=Math.pow(a,(n+0.0)/m);
		System.out.println("Comparer :"+Math.pow(a,n)+" "+Math.pow(b,m)); 
		
		
		
		
		for(int i=0;i<module;i++){
			redColor[i]=generator.nextFloat(); 
			blueColor[i]=generator.nextFloat(); 
			greenColor[i]=generator.nextFloat(); 
		}
		
		
		// Calcul des angles
		double u[]={1+1/a+b/a,1+1/a+1/b,1+1/b+a/b,1+a+a/b,1+a+b,1+b+b/a};
		double theta[]={Math.acos((u[0]-b/(a*a))/(u[0]+b/(a*a))),
						Math.acos((u[1]-1/(a*b))/(u[1]+1/(a*b))),
						Math.acos((u[2]-a/(b*b))/(u[2]+a/(b*b))),
						Math.acos((u[3]-a*a/b)/(u[3]+a*a/b)),
						Math.acos((u[4]-a*b)/(u[4]+a*b)),
						Math.acos((u[5]-b*b/a)/(u[5]+b*b/a))
		};
	
		
		double radiusCoef[]={b/a,1.0/a,1.0/b,a/b,a,b};
		
		
		double rotationAngle[]=new double[6];
		rotationAngle[0]=Math.PI-(theta[0]+theta[1]+theta[2]); 
		rotationAngle[1]=Math.PI-(theta[1]+theta[2]+theta[3]); 
		rotationAngle[2]=Math.PI-(theta[2]+theta[3]+theta[4]);
		rotationAngle[3]=Math.PI-(theta[3]+theta[4]+theta[5]); 
		rotationAngle[4]=Math.PI-(theta[4]+theta[5]+theta[0]); 
		rotationAngle[5]=Math.PI-(theta[5]+theta[0]+theta[1]); 
		
		
		
		Polygon background=new Polygon(new int[]{0,0,X,Y},new int[]{0,X,Y,0},4);
		primeIP.setColor(new Color(0.99f,0.99f,0.99f));
		
		primeIP.fillPolygon(background);
		
		
		primeIP.setFont(new Font(null,Font.ITALIC,60));
		primeIP.setColor(Color.BLACK);
		primeIP.setLineWidth(5); 
		
		primeIP.moveTo(150,80); 
		//primeIP.drawString("a="+a+"\n"+"b="+b+"\n"+"n="+n+"\n"+"m="+m);
	
		setProcessor("Verifying", primeIP);
		/*******************************************************/
		DoyleCircle init=new DoyleCircle(0.5,0.5,0,0.01,0,0); // 0.05
		
		drawCircle(init); 
		memoire.add(init);
		traces.add(init); 
		
		int iter=0; 
		while((!memoire.isEmpty())&&(iter++<3000)){
			int index=0; 
			DoyleCircle seed=memoire.get(index); 
			memoire.remove(seed); 
			if(!traites.contains(seed)){
				traites.add(seed); 
				if(!traces.contains(seed)) {drawCircle(seed);traces.add(seed);} 
				
				double theta0=seed.getRotation();
				
				for(int k=0;k<6;k++){
					double rad1=seed.getRadius()*(1+radiusCoef[k]); 
					double nX1=seed.getXcenter()+rad1*Math.cos(theta0);
					double nY1=seed.getYcenter()+rad1*Math.sin(theta0);
					double angle1=seed.getRotation()+rotationAngle[k]; 
					DoyleCircle c1=new DoyleCircle(nX1,nY1,angle1,seed.getRadius()*radiusCoef[k],0,0);
					if(!memoire.contains(c1)) memoire.add(c1);
					theta0+=theta[k];
					}
			}// if not traite
		}// while memoire ! empty	
		
		show();
	}	
}
	
	
	